
/**
 * 网页元素观察者
 * 对网页指定div进行可视化监视，返回当前可视化div，如果可视的有多个，则返回第一个
 * 使用: 
 *  1.import ElmentObserver from '@/utils/elmentobserver'
 *  2.new Observer(options);
 *  options的参数示例：
 * {
 *  el:'',  需要被观察的元素
 *  callback:'',    返回第一个（或者位于最前面的）可视化元素
 *  rootMargin:'',  这个东西看需要，具体看IntersectionObserver文档
 * }
 */
class ElmentObserver {
    constructor(options) {
        let el = options.el;
        if(!el) {
            throw Error('el is required');
        }
        this.callback = options.callback;
        if(!this.callback) {
            throw Error('callback is required');
        }
        let rootMargin = options.rootMargin;
        let opt = {};
        if(rootMargin) {
            opt.rootMargin = rootMargin;
        }
        this.items = document.querySelectorAll(el);

        this.canseeitemsqueue = [];   //可视化元素队列
        this.curY = 0;  //当前高亮区域的y左边，用于判断上滚还是下滚
        this.initStatus = 0;
        this.io = new IntersectionObserver((entries) => {
            if(!this.initStatus) {
                this.init(entries);
            } else {
                this.handle(entries);
            }
        },opt);
        this.startObserve();
    }

    //IntersectionObserver初始化，收集可视化元素，返回第一个可视元素
    init(entries) {
        this.canseeitemsqueue = [];
        for(let i = 0; i < entries.length;i++) {
            let item = entries[i].target;
            if (entries[i].isIntersecting) {
                let y = entries[i].boundingClientRect.y;
                this.canseeitemsqueue.push({item,y});
            }
        }
        this.initStatus = 1;
        this.curY = this.canseeitemsqueue[0].y;
        this.callback(this.canseeitemsqueue[0]);
    }

    //有元素进入/离开可视化时
    handle(entries) {
        for(let i = 0; i < entries.length;i++) {
            let item = entries[i].target;
            let y = entries[i].boundingClientRect.y;
            if (entries[i].isIntersecting) {
                //有元素进入可视化区域
                let target = {item,y};
                if(y < this.curY) {
                    //想上滚动，上面的就是最前面的
                    this.canseeitemsqueue.unshift(target);
                    this.curY = y;
                    this.callback(this.canseeitemsqueue[0]);
                } else {
                    //向下滚动，加到末尾
                    this.canseeitemsqueue.push(target);
                    this.curY = this.canseeitemsqueue[0].y;
                    this.callback(this.canseeitemsqueue[0]);
                }
            } else {
                //有区域离开
                if(y > this.curY) {
                    //底部的离开
                    this.canseeitemsqueue.pop();
                } else {
                    //顶部的离开
                    this.canseeitemsqueue.shift();
                }
                if(this.canseeitemsqueue.length > 0) {

                    this.curY = this.canseeitemsqueue[0].y;
                    this.callback(this.canseeitemsqueue[0]);
                }
            }
        }
    }

    startObserve() {
        for (let i = 0; i < this.items.length;i++) {
            let item = this.items[i];
            this.io.observe(item);
        }
    }
    stop() {
        this.io.disconnect();
        this.io = null;
    }
}

export default ElmentObserver;